/**
 * 
 */
package qy.jalgotrade.optimizer.base;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * Sinc for backtest results. This class is thread safe. 用来存放 回测结果.
 * 
 * @author c-geo
 *
 */
public abstract class AbstractResultSinc {

	private Results __bestResult;

	private Predicate<Results> __resultFilter;

	private List<Results> __allResults;

	/**
	 * 
	 */
	public AbstractResultSinc() {

		this(null, false);
	}

	/**
	 * 
	 * @param resultFilter
	 */
	public AbstractResultSinc(Predicate<Results> resultFilter) {

		this(resultFilter, false);
	}

	/**
	 * 
	 * @param resultFilter
	 * @param recordAllResults
	 */
	public AbstractResultSinc(Predicate<Results> resultFilter, boolean recordAllResults) {

		__bestResult = null;
		__resultFilter = resultFilter;
		if (recordAllResults) {
			__allResults = new ArrayList<>();
		} else {
			__allResults = null;
		}
	}

	/**
	 * 
	 * @return
	 */
	public boolean getRecordAllResults() {

		return __allResults != null;
	}

	/**
	 * Push strategy results obtained by running the strategy with the given parameters.
	 * 
	 * @param aBatchResults
	 * @param bestResult    The result obtained by running the strategy with the given parameters.
	 * @param goal
	 */
	public synchronized void push(List<Results> aBatchResults, Results bestResult, OptimizingGoal goal) {

		if (__allResults != null) {
			__allResults.addAll(aBatchResults);
		}

		if (__resultFilter != null && !__resultFilter.test(bestResult)) {
			return;
		}

		onNewResult(bestResult, goal);

		if (bestResult != null && goal != null) {

			if (__bestResult == null) {
				// on 1st result:
				updateBest(bestResult);
			} else {
				doUpdateBestResultAndParameters(bestResult, goal);
			}

			onNewBestResult(bestResult, goal);
		}
	}

	/**
	 * 
	 * @param newResult
	 * @param goal
	 */
	protected abstract void doUpdateBestResultAndParameters(Results newResult, OptimizingGoal goal);

	/**
	 * 
	 * @return
	 */
	public synchronized Results getBest() {

		return __bestResult;
	}

	/**
	 * 
	 * @param bestResult
	 */
	protected synchronized void updateBest(Results bestResult) {

		__bestResult = bestResult;
	}

	/**
	 * 
	 * @param result
	 * @param goal
	 */
	public void onNewResult(Results result, OptimizingGoal goal) {

	}

	/**
	 * 
	 * @param result
	 * @param goal
	 */
	public void onNewBestResult(Results result, OptimizingGoal goal) {

	}
}
